From 3a91dcc0970df549608f05fbd811c4b486aee2ab Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 5 Jul 2005 16:08:03 +0000 Subject: [PATCH] Here are two patches which update the hypercall interfaces to use 64-bit values for both page table entries and physical addresses. These changes are needed to use more than 4GB with PAE paging enabled. The first patch is a pretty straightforward update for xen, it simply makes the values 64-bit wide everythere. The second patch adapts the linux kernel to the hypercall interface changes. It also introduces two MULTI_* functions (for the update_va_mapping hypercalls) which have simliar behavior like the HYPERVISOR_* counterparts but fill multicall_entry_t instead of doing the call directly. The tools don't need source code changes, but must be rebuilt due to the change in the xen public header file. Domain0 boots fine, unpriviliged domain boots fine with fully functional networking. Note this is non-PAE mode, tools don't have support for PAE domU boots yet. Signed-off-by: Gerd Knorr --- .../drivers/xen/blkback/blkback.c | 15 +++---- .../drivers/xen/netback/netback.c | 23 ++++------ .../drivers/xen/netfront/netfront.c | 12 ++--- .../drivers/xen/usbback/usbback.c | 24 +++++----- .../include/asm-xen/asm-i386/hypercall.h | 25 ++++++++--- .../include/asm-xen/hypervisor.h | 45 +++++++++++++++++++ xen/arch/x86/mm.c | 15 +++---- xen/include/public/dom0_ops.h | 2 +- xen/include/public/xen.h | 4 +- 9 files changed, 103 insertions(+), 62 deletions(-) diff --git a/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c index 8f78b2376c..f44c70eb03 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c @@ -141,10 +141,8 @@ static void fast_flush_area(int idx, int nr_pages) for ( i = 0; i < nr_pages; i++ ) { - mcl[i].op = __HYPERVISOR_update_va_mapping; - mcl[i].args[0] = MMAP_VADDR(idx, i); - mcl[i].args[1] = 0; - mcl[i].args[2] = 0; + MULTI_update_va_mapping(mcl+i, MMAP_VADDR(idx, i), + __pte(0), 0); } mcl[nr_pages-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL; @@ -545,11 +543,10 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) for ( i = 0; i < nseg; i++ ) { - mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain; - mcl[i].args[0] = MMAP_VADDR(pending_idx, i); - mcl[i].args[1] = (seg[i].buf & PAGE_MASK) | remap_prot; - mcl[i].args[2] = 0; - mcl[i].args[3] = blkif->domid; + MULTI_update_va_mapping_otherdomain( + mcl+i, MMAP_VADDR(pending_idx, i), + pfn_pte_ma(seg[i].buf >> PAGE_SHIFT, remap_prot), + 0, blkif->domid); #ifdef CONFIG_XEN_BLKDEV_TAP_BE if ( blkif->is_blktap ) mcl[i].args[3] = ID_TO_DOM(req->id); diff --git a/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c index faf6458083..45e542919d 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c @@ -234,11 +234,9 @@ static void net_rx_action(unsigned long unused) * Heed the comment in pgtable-2level.h:pte_page(). :-) */ phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn; - - mcl->op = __HYPERVISOR_update_va_mapping; - mcl->args[0] = vdata; - mcl->args[1] = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL; - mcl->args[2] = 0; + + MULTI_update_va_mapping(mcl, vdata, + pfn_pte_ma(new_mfn, PAGE_KERNEL), 0); mcl++; mcl->op = __HYPERVISOR_mmuext_op; @@ -425,10 +423,8 @@ static void net_tx_action(unsigned long unused) while ( dc != dp ) { pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; - mcl[0].op = __HYPERVISOR_update_va_mapping; - mcl[0].args[0] = MMAP_VADDR(pending_idx); - mcl[0].args[1] = 0; - mcl[0].args[2] = 0; + MULTI_update_va_mapping(mcl, MMAP_VADDR(pending_idx), + __pte(0), 0); mcl++; } @@ -571,11 +567,10 @@ static void net_tx_action(unsigned long unused) /* Packets passed to netif_rx() must have some headroom. */ skb_reserve(skb, 16); - mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain; - mcl[0].args[0] = MMAP_VADDR(pending_idx); - mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL; - mcl[0].args[2] = 0; - mcl[0].args[3] = netif->domid; + MULTI_update_va_mapping_otherdomain( + mcl, MMAP_VADDR(pending_idx), + pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL), + 0, netif->domid); mcl++; memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq)); diff --git a/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c index 0ae6f7a40a..419a2c336b 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c @@ -395,10 +395,8 @@ static void network_alloc_rx_buffers(struct net_device *dev) phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = INVALID_P2M_ENTRY; - rx_mcl[i].op = __HYPERVISOR_update_va_mapping; - rx_mcl[i].args[0] = (unsigned long)skb->head; - rx_mcl[i].args[1] = 0; - rx_mcl[i].args[2] = 0; + MULTI_update_va_mapping(rx_mcl+i, (unsigned long)skb->head, + __pte(0), 0); } /* After all PTEs have been zapped we blow away stale TLB entries. */ @@ -585,10 +583,8 @@ static int netif_poll(struct net_device *dev, int *pbudget) mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; mmu->val = __pa(skb->head) >> PAGE_SHIFT; mmu++; - mcl->op = __HYPERVISOR_update_va_mapping; - mcl->args[0] = (unsigned long)skb->head; - mcl->args[1] = (rx->addr & PAGE_MASK) | __PAGE_KERNEL; - mcl->args[2] = 0; + MULTI_update_va_mapping(mcl, (unsigned long)skb->head, + pfn_pte_ma(rx->addr >> PAGE_SHIFT, PAGE_KERNEL), 0); mcl++; phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = diff --git a/linux-2.6.11-xen-sparse/drivers/xen/usbback/usbback.c b/linux-2.6.11-xen-sparse/drivers/xen/usbback/usbback.c index ac73bd0f2f..ad803ab3f5 100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/usbback/usbback.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/usbback/usbback.c @@ -189,10 +189,8 @@ static void fast_flush_area(int idx, int nr_pages) for ( i = 0; i < nr_pages; i++ ) { - mcl[i].op = __HYPERVISOR_update_va_mapping; - mcl[i].args[0] = MMAP_VADDR(idx, i); - mcl[i].args[1] = 0; - mcl[i].args[2] = 0; + MULTI_update_va_mapping(mcl+i, MMAP_VADDR(idx, i), + __pte(0), 0); } mcl[nr_pages-1].args[2] = UVMF_TLB_FLUSH|UVMF_ALL; @@ -651,11 +649,10 @@ static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req) for ( i = 0, offset = 0; offset < req->length; i++, offset += PAGE_SIZE ) { - mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain; - mcl[i].args[0] = MMAP_VADDR(pending_idx, i); - mcl[i].args[1] = ((buffer_mach & PAGE_MASK) + offset) | remap_prot; - mcl[i].args[2] = 0; - mcl[i].args[3] = up->domid; + MULTI_update_va_mapping_otherdomain( + mcl+i, MMAP_VADDR(pending_idx, i), + pfn_pte_ma(buffer_mach >> PAGE_SHIFT, remap_prot), + 0, up->domid); phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] = FOREIGN_FRAME((buffer_mach + offset) >> PAGE_SHIFT); @@ -667,11 +664,10 @@ static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req) if ( req->pipe_type == 0 && req->num_iso > 0 ) /* Maybe schedule ISO... */ { /* Map in ISO schedule, if necessary. */ - mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain; - mcl[i].args[0] = MMAP_VADDR(pending_idx, i); - mcl[i].args[1] = (req->iso_schedule & PAGE_MASK) | remap_prot; - mcl[i].args[2] = 0; - mcl[i].args[3] = up->domid; + MULTI_update_va_mapping_otherdomain( + mcl+i, MMAP_VADDR(pending_idx, i), + pfn_pte_ma(req->iso_schedule >> PAGE_SHIFT, remap_prot), + 0, up->domid); phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] = FOREIGN_FRAME(req->iso_schedule >> PAGE_SHIFT); diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h index 98b2b999fd..3abe82e3df 100644 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h @@ -371,13 +371,19 @@ HYPERVISOR_update_va_mapping( unsigned long va, pte_t new_val, unsigned long flags) { int ret; - unsigned long ign1, ign2, ign3; + unsigned long ign1, ign2, ign3, ign4; __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3) + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) : "0" (__HYPERVISOR_update_va_mapping), - "1" (va), "2" ((new_val).pte_low), "3" (flags) + "1" (va), "2" ((new_val).pte_low), +#ifdef CONFIG_X86_PAE + "3" ((new_val).pte_high), +#else + "3" (0), +#endif + "4" (flags) : "memory" ); if ( unlikely(ret < 0) ) @@ -473,13 +479,20 @@ HYPERVISOR_update_va_mapping_otherdomain( unsigned long va, pte_t new_val, unsigned long flags, domid_t domid) { int ret; - unsigned long ign1, ign2, ign3, ign4; + unsigned long ign1, ign2, ign3, ign4, ign5; __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4) + : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), + "=S" (ign4), "=D" (ign5) : "0" (__HYPERVISOR_update_va_mapping_otherdomain), - "1" (va), "2" ((new_val).pte_low), "3" (flags), "4" (domid) : + "1" (va), "2" ((new_val).pte_low), +#ifdef CONFIG_X86_PAE + "3" ((new_val).pte_high), +#else + "3" (0), +#endif + "4" (flags), "5" (domid) : "memory" ); return ret; diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h index a2929951d2..0ee9e3d12e 100644 --- a/linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h @@ -139,4 +139,49 @@ unsigned long allocate_empty_lowmem_region(unsigned long pages); #include +static inline void +MULTI_update_va_mapping( + multicall_entry_t *mcl, unsigned long va, + pte_t new_val, unsigned long flags) +{ + mcl->op = __HYPERVISOR_update_va_mapping; + mcl->args[0] = va; +#if defined(CONFIG_X86_64) + mcl->args[1] = new_val.pte; + mcl->args[2] = flags; +#elif defined(CONFIG_X86_PAE) + mcl->args[1] = new_val.pte_low; + mcl->args[2] = new_val.pte_high; + mcl->args[3] = flags; +#else + mcl->args[1] = new_val.pte_low; + mcl->args[2] = 0; + mcl->args[3] = flags; +#endif +} + +static inline void +MULTI_update_va_mapping_otherdomain( + multicall_entry_t *mcl, unsigned long va, + pte_t new_val, unsigned long flags, domid_t domid) +{ + mcl->op = __HYPERVISOR_update_va_mapping_otherdomain; + mcl->args[0] = va; +#if defined(CONFIG_X86_64) + mcl->args[1] = new_val.pte; + mcl->args[2] = flags; + mcl->args[3] = domid; +#elif defined(CONFIG_X86_PAE) + mcl->args[1] = new_val.pte_low; + mcl->args[2] = new_val.pte_high; + mcl->args[3] = flags; + mcl->args[4] = domid; +#else + mcl->args[1] = new_val.pte_low; + mcl->args[2] = 0; + mcl->args[3] = flags; + mcl->args[4] = domid; +#endif +} + #endif /* __HYPERVISOR_H__ */ diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 06e47e5eea..2c530cf261 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2020,7 +2020,8 @@ int do_mmu_update( } va = map_domain_page_with_cache(mfn, &mapcache); - va = (void *)((unsigned long)va + (req.ptr & ~PAGE_MASK)); + va = (void *)((unsigned long)va + + (unsigned long)(req.ptr & ~PAGE_MASK)); page = &frame_table[mfn]; switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask ) @@ -2164,7 +2165,7 @@ int do_mmu_update( break; default: - MEM_LOG("Invalid page update command %lx", req.ptr); + MEM_LOG("Invalid page update command %x", cmd); break; } @@ -2251,11 +2252,10 @@ int update_grant_va_mapping(unsigned long va, } -int do_update_va_mapping(unsigned long va, - unsigned long val32, +int do_update_va_mapping(unsigned long va, u64 val64, unsigned long flags) { - l1_pgentry_t val = l1e_from_intpte(val32); + l1_pgentry_t val = l1e_from_intpte(val64); struct vcpu *v = current; struct domain *d = v->domain; unsigned int cpu = v->processor; @@ -2349,8 +2349,7 @@ int do_update_va_mapping(unsigned long va, return rc; } -int do_update_va_mapping_otherdomain(unsigned long va, - unsigned long val32, +int do_update_va_mapping_otherdomain(unsigned long va, u64 val64, unsigned long flags, domid_t domid) { @@ -2368,7 +2367,7 @@ int do_update_va_mapping_otherdomain(unsigned long va, return -ESRCH; } - rc = do_update_va_mapping(va, val32, flags); + rc = do_update_va_mapping(va, val64, flags); return rc; } diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index 19ad0efab5..419e647746 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -19,7 +19,7 @@ * This makes sure that old versions of dom0 tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define DOM0_INTERFACE_VERSION 0xAAAA100A +#define DOM0_INTERFACE_VERSION 0xAAAA100B /************************************************************************/ diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index 357761f544..3e25532f19 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -274,8 +274,8 @@ typedef u16 domid_t; */ typedef struct { - memory_t ptr; /* Machine address of PTE. */ - memory_t val; /* New contents of PTE. */ + u64 ptr; /* Machine address of PTE. */ + u64 val; /* New contents of PTE. */ } mmu_update_t; /* -- 2.30.2